package data.platform;

import data.platform.rest.domain.Metric;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Slf4j
public class MockDataPointHttp {

    List<IpRange> ipRanges;

    private WebClient webClient;

    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    private static final List<String> METRICS = Arrays.asList("CPU", "MEM");

    public MockDataPointHttp() {
        init();
    }

    public MockDataPointHttp(List<IpRange> ipRanges) {
        this();
        this.ipRanges = ipRanges;
    }

    private void init() {
        webClient = WebClient.builder()
                .baseUrl("http://localhost:30510")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();

        scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
    }

    public void sendDataPoint() {
        scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
            try {
                List<Metric> metrics = new ArrayList<>();
                for (IpRange ipRange : ipRanges) {
                    List<String> ipRanges = createIpRange(ipRange.getStartIp(), ipRange.getEndIp());
                    for (String ip : ipRanges) {
                        ipRange.getMetrics().forEach(metricName -> {
                            Metric metric = new Metric();
                            metric.setName(metricName);
                            metric.setTags(createTag(ip, ipRange.getLocation(), ipRange.getRoom(), ipRange.getMoType()));
                            Object[] dataPoint = new Object[]{new Date().getTime(), ThreadLocalRandom.current().nextInt(100)};
                            List<Object[]> samplePoints = Collections.singletonList(dataPoint);
                            metric.setSamplePoints(samplePoints);

                            metrics.add(metric);
                        });
                    }
                }

                webClient.post()
                        .uri("/api/v1/datapoints")
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .body(Mono.just(metrics), List.class)
                        .exchangeToMono(response -> Mono.just(response.statusCode()))
                        .doOnNext(httpStatus -> log.info(httpStatus.toString()))
                        .doOnError(error -> log.error("", error))
                        .block();
            } catch (Exception ex) {
                log.error("", ex);
            }
        }, 0, 10, TimeUnit.SECONDS);
    }

    private List<String> createIpRange(String startIp, String endIp) {
        List<String> ipRanges = new ArrayList<>();
        String[] startParts = startIp.split("(?<=\\.)(?!.*\\.)");
        String[] endParts = endIp.split("(?<=\\.)(?!.*\\.)");

        int first = Integer.parseInt(startParts[1]);
        int last = Integer.parseInt(endParts[1]);

        for (int i = first; i <= last; i++) {
            ipRanges.add(startParts[0] + i);
        }
        return ipRanges;
    }

    private Map<String, String> createTag(String ip, String location, String room, String moType) {
        Map<String, String> tags = new HashMap<>();
        tags.put("ip", ip);
        tags.put("location", location);
        tags.put("room", room);
        tags.put("moc", moType);
        return tags;
    }

    public static void main(String[] args) {
        List<IpRange> ipRanges = new ArrayList<>();
        ipRanges.add(IpRange.builder().startIp("30.0.0.0")
                .endIp("30.0.0.10")
                .moType("NetworkDevice")
                .location("Shanghai")
                .room("YiShan@700")
                .metrics(Arrays.asList("CPU", "MEM"))
                .build());

        ipRanges.add(IpRange.builder().startIp("10.0.0.0")
                .endIp("10.0.0.10")
                .moType("Windows")
                .location("BeiJin")
                .room("HaiDing@1024")
                .metrics(Arrays.asList("CPU_LOAD", "MEM_LOAD"))
                .build());
        MockDataPointHttp mockDataPointHttp = new MockDataPointHttp(ipRanges);
        mockDataPointHttp.sendDataPoint();
    }


}
